2 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
3 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <sys/types.h>
20 #include <sys/utsname.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <sys/types.h>
33 #include <libubox/usock.h>
34 #include <libubox/uloop.h>
35 #include <libubox/avl-cmp.h>
36 #include <libubox/utils.h>
38 #include "interface.h"
44 static struct uloop_fd ufd
[] = {
45 [SOCK_UC_IPV4
] = { .fd
= -1 },
46 [SOCK_UC_IPV6
] = { .fd
= -1 },
47 [SOCK_MC_IPV4
] = { .fd
= -1 },
48 [SOCK_MC_IPV6
] = { .fd
= -1 },
52 interface_send_packet4(struct interface
*iface
, struct sockaddr_in
*to
, struct iovec
*iov
, int iov_len
)
54 static size_t cmsg_data
[( CMSG_SPACE(sizeof(struct in_pktinfo
)) / sizeof(size_t)) + 1];
55 static struct sockaddr_in a
= {};
56 static struct msghdr m
= {
57 .msg_name
= (struct sockaddr
*) &a
,
58 .msg_namelen
= sizeof(a
),
59 .msg_control
= cmsg_data
,
60 .msg_controllen
= CMSG_LEN(sizeof(struct in_pktinfo
)),
62 struct in_pktinfo
*pkti
;
66 a
.sin_family
= AF_INET
;
67 a
.sin_port
= htons(MCAST_PORT
);
69 m
.msg_iovlen
= iov_len
;
71 memset(cmsg_data
, 0, sizeof(cmsg_data
));
72 cmsg
= CMSG_FIRSTHDR(&m
);
73 cmsg
->cmsg_len
= m
.msg_controllen
;
74 cmsg
->cmsg_level
= IPPROTO_IP
;
75 cmsg
->cmsg_type
= IP_PKTINFO
;
77 pkti
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
78 pkti
->ipi_ifindex
= iface
->ifindex
;
80 fd
= ufd
[iface
->type
].fd
;
81 if (interface_multicast(iface
)) {
82 a
.sin_addr
.s_addr
= inet_addr(MCAST_ADDR
);
84 fprintf(stderr
, "Ignoring IPv4 address for multicast interface\n");
86 a
.sin_addr
.s_addr
= to
->sin_addr
.s_addr
;
89 return sendmsg(fd
, &m
, 0);
93 interface_send_packet6(struct interface
*iface
, struct sockaddr_in6
*to
, struct iovec
*iov
, int iov_len
)
95 static size_t cmsg_data
[( CMSG_SPACE(sizeof(struct in6_pktinfo
)) / sizeof(size_t)) + 1];
96 static struct sockaddr_in6 a
= {};
97 static struct msghdr m
= {
98 .msg_name
= (struct sockaddr
*) &a
,
99 .msg_namelen
= sizeof(a
),
100 .msg_control
= cmsg_data
,
101 .msg_controllen
= CMSG_LEN(sizeof(struct in6_pktinfo
)),
103 struct in6_pktinfo
*pkti
;
104 struct cmsghdr
*cmsg
;
107 a
.sin6_family
= AF_INET6
;
108 a
.sin6_port
= htons(MCAST_PORT
);
109 a
.sin6_scope_id
= iface
->ifindex
;
111 m
.msg_iovlen
= iov_len
;
113 memset(cmsg_data
, 0, sizeof(cmsg_data
));
114 cmsg
= CMSG_FIRSTHDR(&m
);
115 cmsg
->cmsg_len
= m
.msg_controllen
;
116 cmsg
->cmsg_level
= IPPROTO_IPV6
;
117 cmsg
->cmsg_type
= IPV6_PKTINFO
;
119 pkti
= (struct in6_pktinfo
*) CMSG_DATA(cmsg
);
120 pkti
->ipi6_ifindex
= iface
->ifindex
;
122 fd
= ufd
[iface
->type
].fd
;
123 if (interface_multicast(iface
)) {
124 inet_pton(AF_INET6
, MCAST_ADDR6
, &a
.sin6_addr
);
126 fprintf(stderr
, "Ignoring IPv6 address for multicast interface\n");
128 a
.sin6_addr
= to
->sin6_addr
;
131 return sendmsg(fd
, &m
, 0);
135 interface_send_packet(struct interface
*iface
, struct sockaddr
*to
, struct iovec
*iov
, int iov_len
)
137 if (!interface_multicast(iface
) && !to
) {
138 fprintf(stderr
, "No IP address specified for unicast interface\n");
144 fprintf(stderr
, "TX ipv%d: %s\n", interface_ipv6(iface
) ? 6 : 4, iface
->name
);
145 fprintf(stderr
, " multicast: %d\n", interface_multicast(iface
));
148 if (interface_ipv6(iface
))
149 return interface_send_packet6(iface
, (struct sockaddr_in6
*)to
, iov
, iov_len
);
151 return interface_send_packet4(iface
, (struct sockaddr_in
*)to
, iov
, iov_len
);
154 static struct interface
*interface_lookup(unsigned int ifindex
, enum umdns_socket_type type
)
156 struct interface
*iface
;
158 vlist_for_each_element(&interfaces
, iface
, node
)
159 if (iface
->ifindex
== ifindex
&& iface
->type
== type
)
165 static void interface_free(struct interface
*iface
)
167 announce_free(iface
);
168 free(iface
->addrs
.v4
);
173 interface_valid_src(void *ip1
, void *mask
, void *ip2
, int len
)
183 for (i
= 0; i
< len
; i
++, i1
++, i2
++, m
++) {
184 if ((*i1
& *m
) != (*i2
& *m
))
192 read_socket4(struct uloop_fd
*u
, unsigned int events
)
194 enum umdns_socket_type type
= (enum umdns_socket_type
)(u
- ufd
);
195 struct interface
*iface
;
196 static uint8_t buffer
[8 * 1024];
198 char cmsg
[CMSG_SPACE(sizeof(struct in_pktinfo
)) + CMSG_SPACE(sizeof(int)) + 1];
199 struct cmsghdr
*cmsgptr
;
202 struct sockaddr_in from
;
205 struct in_pktinfo
*inp
= NULL
;
206 bool valid_src
= false;
213 iov
[0].iov_base
= buffer
;
214 iov
[0].iov_len
= sizeof(buffer
);
216 memset(&msg
, 0, sizeof(msg
));
217 msg
.msg_name
= (struct sockaddr
*) &from
;
218 msg
.msg_namelen
= sizeof(struct sockaddr_in
);
221 msg
.msg_control
= &cmsg
;
222 msg
.msg_controllen
= sizeof(cmsg
);
224 len
= recvmsg(u
->fd
, &msg
, flags
);
226 perror("read failed");
229 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
; cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
230 void *c
= CMSG_DATA(cmsgptr
);
232 switch (cmsgptr
->cmsg_type
) {
234 inp
= ((struct in_pktinfo
*) c
);
238 ttl
= (uint8_t) *((int *) c
);
242 fprintf(stderr
, "unknown cmsg %x\n", cmsgptr
->cmsg_type
);
250 iface
= interface_lookup(inp
->ipi_ifindex
, type
);
257 fprintf(stderr
, "RX ipv4: %s\n", iface
->name
);
258 fprintf(stderr
, " multicast: %d\n", interface_multicast(iface
));
259 inet_ntop(AF_INET
, &from
.sin_addr
, buf
, 256);
260 fprintf(stderr
, " src %s:%d\n", buf
, ntohs(from
.sin_port
));
261 inet_ntop(AF_INET
, &inp
->ipi_spec_dst
, buf
, 256);
262 fprintf(stderr
, " dst %s\n", buf
);
263 inet_ntop(AF_INET
, &inp
->ipi_addr
, buf
, 256);
264 fprintf(stderr
, " real %s\n", buf
);
265 fprintf(stderr
, " ttl %u\n", ttl
);
268 for (size_t i
= 0; i
< iface
->addrs
.n_addr
; i
++) {
269 if (!interface_valid_src((void *)&iface
->addrs
.v4
[i
].addr
,
270 (void *)&iface
->addrs
.v4
[i
].mask
,
271 (void *) &from
.sin_addr
, 4)) {
280 dns_handle_packet(iface
, (struct sockaddr
*) &from
, ntohs(from
.sin_port
), buffer
, len
);
284 read_socket6(struct uloop_fd
*u
, unsigned int events
)
286 enum umdns_socket_type type
= (enum umdns_socket_type
)(u
- ufd
);
287 struct interface
*iface
;
288 static uint8_t buffer
[8 * 1024];
290 char cmsg6
[CMSG_SPACE(sizeof(struct in6_pktinfo
)) + CMSG_SPACE(sizeof(int)) + 1];
291 struct cmsghdr
*cmsgptr
;
294 struct sockaddr_in6 from
;
297 struct in6_pktinfo
*inp
= NULL
;
298 bool valid_src
= false;
305 iov
[0].iov_base
= buffer
;
306 iov
[0].iov_len
= sizeof(buffer
);
308 memset(&msg
, 0, sizeof(msg
));
309 msg
.msg_name
= (struct sockaddr
*) &from
;
310 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
313 msg
.msg_control
= &cmsg6
;
314 msg
.msg_controllen
= sizeof(cmsg6
);
316 len
= recvmsg(u
->fd
, &msg
, flags
);
318 perror("read failed");
321 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
; cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
)) {
322 void *c
= CMSG_DATA(cmsgptr
);
324 switch (cmsgptr
->cmsg_type
) {
326 inp
= ((struct in6_pktinfo
*) c
);
330 ttl
= (uint8_t) *((int *) c
);
334 fprintf(stderr
, "unknown cmsg %x\n", cmsgptr
->cmsg_type
);
342 iface
= interface_lookup(inp
->ipi6_ifindex
, type
);
349 fprintf(stderr
, "RX ipv6: %s\n", iface
->name
);
350 fprintf(stderr
, " multicast: %d\n", interface_multicast(iface
));
351 inet_ntop(AF_INET6
, &from
.sin6_addr
, buf
, 256);
352 fprintf(stderr
, " src %s:%d\n", buf
, ntohs(from
.sin6_port
));
353 inet_ntop(AF_INET6
, &inp
->ipi6_addr
, buf
, 256);
354 fprintf(stderr
, " dst %s\n", buf
);
355 fprintf(stderr
, " ttl %u\n", ttl
);
358 for (size_t i
= 0; i
< iface
->addrs
.n_addr
; i
++) {
359 if (!interface_valid_src((void *)&iface
->addrs
.v6
[i
].addr
,
360 (void *)&iface
->addrs
.v6
[i
].mask
,
361 (void *)&from
.sin6_addr
, 6)) {
370 dns_handle_packet(iface
, (struct sockaddr
*) &from
, ntohs(from
.sin6_port
), buffer
, len
);
374 interface_mcast_setup4(struct interface
*iface
)
376 struct ip_mreqn mreq
;
377 struct sockaddr_in sa
= {};
378 int fd
= ufd
[SOCK_MC_IPV4
].fd
;
380 sa
.sin_family
= AF_INET
;
381 sa
.sin_port
= htons(MCAST_PORT
);
382 inet_pton(AF_INET
, MCAST_ADDR
, &sa
.sin_addr
);
384 memset(&mreq
, 0, sizeof(mreq
));
385 mreq
.imr_multiaddr
= sa
.sin_addr
;
386 mreq
.imr_ifindex
= iface
->ifindex
;
387 mreq
.imr_address
.s_addr
= iface
->addrs
.v4
[0].addr
.s_addr
;
389 /* Some network drivers have issues with dropping membership of
390 * mcast groups when the iface is down, but don't allow rejoining
391 * when it comes back up. This is an ugly workaround
392 * -- this was copied from avahi --
394 setsockopt(fd
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, &mreq
, sizeof(mreq
));
395 setsockopt(fd
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &mreq
, sizeof(mreq
));
401 interface_mcast_setup6(struct interface
*iface
)
403 struct ipv6_mreq mreq
;
404 struct sockaddr_in6 sa
= {};
405 int fd
= ufd
[SOCK_MC_IPV6
].fd
;
407 sa
.sin6_family
= AF_INET6
;
408 sa
.sin6_port
= htons(MCAST_PORT
);
409 inet_pton(AF_INET6
, MCAST_ADDR6
, &sa
.sin6_addr
);
411 memset(&mreq
, 0, sizeof(mreq
));
412 mreq
.ipv6mr_multiaddr
= sa
.sin6_addr
;
413 mreq
.ipv6mr_interface
= iface
->ifindex
;
415 setsockopt(fd
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
, &mreq
, sizeof(mreq
));
416 setsockopt(fd
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
, &mreq
, sizeof(mreq
));
421 static void interface_start(struct interface
*iface
)
423 if (iface
->type
& SOCKTYPE_BIT_UNICAST
)
426 if (iface
->type
& SOCKTYPE_BIT_IPV6
)
427 interface_mcast_setup6(iface
);
429 interface_mcast_setup4(iface
);
431 dns_send_question(iface
, NULL
, C_DNS_SD
, TYPE_PTR
, 0);
432 announce_init(iface
);
436 iface_equal(struct interface
*if_old
, struct interface
*if_new
)
440 if (if_old
->ifindex
!= if_new
->ifindex
||
441 if_old
->addrs
.n_addr
!= if_new
->addrs
.n_addr
)
444 if (if_old
->type
& SOCKTYPE_BIT_IPV6
)
445 addr_size
= sizeof(*if_old
->addrs
.v6
);
447 addr_size
= sizeof(*if_old
->addrs
.v4
);
448 addr_size
*= if_old
->addrs
.n_addr
;
449 if (memcmp(if_old
->addrs
.v4
, if_new
->addrs
.v4
, addr_size
) != 0)
456 iface_update_cb(struct vlist_tree
*tree
, struct vlist_node
*node_new
,
457 struct vlist_node
*node_old
)
459 struct interface
*if_old
= container_of_safe(node_old
, struct interface
, node
);
460 struct interface
*if_new
= container_of_safe(node_new
, struct interface
, node
);
462 if (if_old
&& if_new
) {
463 if (!iface_equal(if_old
, if_new
))
464 cache_cleanup(if_old
);
465 free(if_old
->addrs
.v4
);
466 if_old
->addrs
= if_new
->addrs
;
472 interface_free(if_old
);
475 interface_start(if_new
);
478 static int interface_init_socket(enum umdns_socket_type type
)
480 struct sockaddr_in6 local6
= {
481 .sin6_family
= AF_INET6
483 struct sockaddr_in local
= {
484 .sin_family
= AF_INET
491 int af
= (type
& SOCKTYPE_BIT_IPV6
) ? AF_INET6
: AF_INET
;
493 if (ufd
[type
].fd
>= 0)
496 ufd
[type
].fd
= fd
= socket(af
, SOCK_DGRAM
, 0);
500 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
502 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
510 setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_TTL
, &ttl
, sizeof(ttl
));
511 setsockopt(fd
, IPPROTO_IP
, IP_TTL
, &ittl
, sizeof(ittl
));
512 setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_LOOP
, &no
, sizeof(no
));
513 local
.sin_port
= htons(MCAST_PORT
);
516 setsockopt(fd
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, &ttl
, sizeof(ttl
));
517 setsockopt(fd
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &ttl
, sizeof(ttl
));
518 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &yes
, sizeof(yes
));
519 setsockopt(fd
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, &no
, sizeof(no
));
520 local6
.sin6_port
= htons(MCAST_PORT
);
524 if (type
& SOCKTYPE_BIT_IPV6
) {
525 ufd
[type
].cb
= read_socket6
;
526 if (bind(fd
, (struct sockaddr
*)&local6
, sizeof(local6
)) < 0)
529 setsockopt(fd
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
, &yes
, sizeof(yes
));
530 setsockopt(fd
, IPPROTO_IPV6
, IPV6_RECVHOPLIMIT
, &yes
, sizeof(yes
));
532 ufd
[type
].cb
= read_socket4
;
533 if (bind(fd
, (struct sockaddr
*)&local
, sizeof(local
)) < 0)
536 setsockopt(fd
, IPPROTO_IP
, IP_PKTINFO
, &yes
, sizeof(yes
));
537 setsockopt(fd
, IPPROTO_IP
, IP_RECVTTL
, &yes
, sizeof(yes
));
540 uloop_fd_add(&ufd
[type
], ULOOP_READ
);
550 __interface_add(const char *name
, enum umdns_socket_type type
,
551 struct interface_addr_list
*list
)
553 struct interface
*iface
;
554 unsigned int ifindex
;
557 if (interface_init_socket(type
))
560 ifindex
= if_nametoindex(name
);
564 iface
= calloc_a(sizeof(*iface
),
565 &id_buf
, strlen(name
) + 3);
567 sprintf(id_buf
, "%d_%s", type
, name
);
568 iface
->name
= id_buf
+ 2;
569 iface
->ifindex
= ifindex
;
571 iface
->addrs
= *list
;
573 vlist_add(&interfaces
, &iface
->node
, id_buf
);
580 int interface_add(const char *name
)
582 struct ifaddrs
*ifap
, *ifa
;
583 struct interface_addr_list addr4
= {}, addr6
= {};
587 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
588 if (strcmp(ifa
->ifa_name
, name
))
590 if (ifa
->ifa_addr
->sa_family
== AF_INET
) {
591 struct sockaddr_in
*sin
;
593 if (cfg_proto
&& (cfg_proto
!= 4))
596 addr4
.v4
= realloc(addr4
.v4
, (addr4
.n_addr
+ 1) * sizeof(*addr4
.v4
));
597 sin
= (struct sockaddr_in
*) ifa
->ifa_addr
;
598 addr4
.v4
[addr4
.n_addr
].addr
= sin
->sin_addr
;
599 sin
= (struct sockaddr_in
*) ifa
->ifa_netmask
;
600 addr4
.v4
[addr4
.n_addr
++].mask
= sin
->sin_addr
;
603 if (ifa
->ifa_addr
->sa_family
== AF_INET6
) {
604 uint8_t ll_prefix
[] = {0xfe, 0x80 };
605 struct sockaddr_in6
*sin6
;
607 if (cfg_proto
&& (cfg_proto
!= 6))
610 sin6
= (struct sockaddr_in6
*) ifa
->ifa_addr
;
611 if (memcmp(&sin6
->sin6_addr
, &ll_prefix
, 2))
614 addr6
.v6
= realloc(addr6
.v6
, (addr6
.n_addr
+ 1) * sizeof(*addr6
.v6
));
615 sin6
= (struct sockaddr_in6
*) ifa
->ifa_addr
;
616 addr6
.v6
[addr6
.n_addr
].addr
= sin6
->sin6_addr
;
617 sin6
= (struct sockaddr_in6
*) ifa
->ifa_netmask
;
618 addr6
.v6
[addr6
.n_addr
++].mask
= sin6
->sin6_addr
;
625 size_t addr_size
= addr4
.n_addr
* sizeof(*addr4
.v4
);
626 void *addr_dup
= malloc(addr_size
);
628 memcpy(addr_dup
, addr4
.v4
, addr_size
);
629 __interface_add(name
, SOCK_UC_IPV4
, &addr4
);
631 __interface_add(name
, SOCK_MC_IPV4
, &addr4
);
635 size_t addr_size
= addr6
.n_addr
* sizeof(*addr6
.v6
);
636 void *addr_dup
= malloc(addr_size
);
638 memcpy(addr_dup
, addr6
.v6
, addr_size
);
639 __interface_add(name
, SOCK_UC_IPV6
, &addr6
);
641 __interface_add(name
, SOCK_MC_IPV6
, &addr6
);
644 return !addr4
.n_addr
&& !addr6
.n_addr
;
647 void interface_shutdown(void)
649 struct interface
*iface
;
651 vlist_for_each_element(&interfaces
, iface
, node
)
652 if (interface_multicast(iface
)) {
653 dns_reply_a(iface
, NULL
, 0);
654 service_announce_services(iface
, NULL
, 0);
657 for (size_t i
= 0; i
< ARRAY_SIZE(ufd
); i
++) {
658 uloop_fd_delete(&ufd
[i
]);
664 struct interface
*interface_get(const char *name
, enum umdns_socket_type type
)
667 snprintf(id_buf
, sizeof(id_buf
), "%d_%s", type
, name
);
668 struct interface
*iface
= vlist_find(&interfaces
, id_buf
, iface
, node
);
672 VLIST_TREE(interfaces
, avl_strcmp
, iface_update_cb
, false, false);